﻿// MathMetric.cpp: implementation of the MathMetric class.
//
//////////////////////////////////////////////////////////////////////
#include "MathMetric.h"
#include <string.h>
#include <stdio.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

/**********************************************************
函数名：foo
功能：定义此函主要是为了让模板具现化
入口参数：无
出口参数：无
说明：该函数必须调用类中所有的公共函数甚至是么有函数，否则
	  在编译过程中将出错
**********************************************************/
MathMetric::MathMetric()
{

}


/**********************************************************
函数名：foo
功能：定义此函主要是为了让模板具现化
入口参数：无
出口参数：无
说明：该函数必须调用类中所有的公共函数甚至是么有函数，否则
	  在编译过程中将出错
**********************************************************/
MathMetric::MathMetric(double*data,unsigned int line,unsigned int clum)
{
	this->line=line;
	this->clum=clum;
	this->data=(double*)malloc(sizeof(double)*line*clum);
	if(!this->data)
		return;
	memcpy((void*)this->data,(void*)data,sizeof(double)*line*clum);
}


/**********************************************************
函数名：foo
功能：定义此函主要是为了让模板具现化
入口参数：无
出口参数：无
说明：该函数必须调用类中所有的公共函数甚至是么有函数，否则
	  在编译过程中将出错
**********************************************************/
MathMetric::~MathMetric()
{
	free(data);
}


/**********************************************************
函数名：foo
功能：定义此函主要是为了让模板具现化
入口参数：无
出口参数：无
说明：该函数必须调用类中所有的公共函数甚至是么有函数，否则
	  在编译过程中将出错
**********************************************************/
/*void foo()
{
MathMetric aa;
aa.multiple(NULL,1,1,NULL,1,1);
aa.devide(NULL,1,1,NULL,1,1);
aa.add(NULL,1,1,NULL,1,1);
aa.sub(NULL,1,1,NULL,1,1);
aa.Inverse(NULL,1);
}*/



/**********************************************************
函数名：Rotate
功能：以图片中心为原点旋转X度
入口参数：doAngle:旋转度数
出口参数：无
说明：函数中计算f1,f2是因为旋转是以图片中心进行的，但实际的算法
	  却是以图片的左上角为原点进行，所以这样处理以后需要将图片
	  平移(f2,f1)
**********************************************************/
 double* MathMetric::add(double* metric1,unsigned int dim1,unsigned int dim2,double* metric2,unsigned int dim3,unsigned int dim4)
{
	double* temp;
	double* result;
	if((dim1!=dim3)&&(dim2!=dim4))
	{
		printf("两矩阵维数不匹配！！！不能相加");
		return NULL;
	}
	result=(double*)malloc(dim1*dim2*sizeof(double));
	assert(result);

	temp=result;

	memset(result,0,dim1*dim2*sizeof(double));
	for(unsigned int i=0;i<dim1*dim2;i++)
	{
		*result++=*metric1+++*metric2++;

	}
	return temp;
}


/**********************************************************
函数名：Rotate
功能：以图片中心为原点旋转X度
入口参数：doAngle:旋转度数
出口参数：无
说明：函数中计算f1,f2是因为旋转是以图片中心进行的，但实际的算法
	  却是以图片的左上角为原点进行，所以这样处理以后需要将图片
	  平移(f2,f1)
**********************************************************/
double* MathMetric::sub(double* metric1,unsigned int dim1,unsigned int dim2,double* metric2,unsigned int dim3,unsigned int dim4)
{
	double* temp;
	double* result;
	if((dim1!=dim3)&&(dim2!=dim4))
	{
		printf("两矩阵维数不匹配！！！");
		return NULL;
	}
	result=(double*)malloc(dim1*dim2*sizeof(double));
	assert(result);
	temp=result;
	memset(result,0,dim1*dim2*sizeof(double));
	for(unsigned int i=0;i<dim1*dim2;i++)
		*result++=*metric1++-*metric2++;
	return temp;
}


/**********************************************************
函数名：Rotate
功能：以图片中心为原点旋转X度
入口参数：doAngle:旋转度数
出口参数：无
说明：函数中计算f1,f2是因为旋转是以图片中心进行的，但实际的算法
	  却是以图片的左上角为原点进行，所以这样处理以后需要将图片
	  平移(f2,f1)
**********************************************************/
double* MathMetric::multiple(double* metric1,unsigned int dim1,unsigned int dim2,double* metric2,unsigned int dim3,unsigned int dim4)
{
	double* temp;
	double* result;
	if(dim2!=dim3)
	{
		printf("两矩阵维数不匹配！！！");
		return NULL;
	}
	result=(double*)malloc(dim1*dim4*sizeof(double));
	assert(result);
	temp=result;
	memset(result,0,dim1*dim4*sizeof(double));
	for(unsigned int j=0;j<dim1;j++)
		for(unsigned int k=0;k<dim4;k++)
		{
			for(unsigned int i=0;i<dim2;i++)
			{
				*result+=(metric1[j*dim2+i]*metric2[i*dim4+k]);
			}
			result++;
		}
	return temp;
}


/**********************************************************
函数名：devide
功能：以图片中心为原点旋转X度
入口参数：doAngle:旋转度数
出口参数：无
说明：函数中计算f1,f2是因为旋转是以图片中心进行的，但实际的算法
	  却是以图片的左上角为原点进行，所以这样处理以后需要将图片
	  平移(f2,f1)
**********************************************************/
double* MathMetric::devide(double* metric1,unsigned int dim1,unsigned int dim2,double* metric2,unsigned int dim3,unsigned int dim4)
{
	if((dim1!=dim3)&&(dim2!=dim4))
	{
		printf("两矩阵维数不匹配！！！");
	}
	double* result=(double*)malloc(dim1*dim4*sizeof(double));
	assert(result);
	memset(result,0,dim1*dim4*sizeof(double));
	return result;
}


/**********************************************************
函数名：reverse
功能：求矩阵的转置矩阵
入口参数：无
出口参数：成功返回true,失败返回false
说明：仅有方正才有转置矩阵
**********************************************************/
bool MathMetric::reverse(double *data, unsigned int line, unsigned int colum)
{
	unsigned int i;
	unsigned int n;
	unsigned temp;
	unsigned temp1;
	i=0;
	n=0;
	temp=0;
	temp1=0;
	if(line!=colum)
		return false;
	for(i=0;i<line;i++)
		for(n=i+1;n<colum;n++)
		{
			temp=i*colum+n;
			temp1=n*colum+i;
			data[temp]+=data[temp1];
			data[temp1]=data[temp]-data[temp1];
			data[temp]-=data[temp1];
		}
	return true;
}


/**********************************************************
函数名：inverse
功能：求矩阵的逆
入口参数：a:矩阵的无素数组的指针，其按行按列存放在一维数组中
		  n:矩阵的维数
出口参数：如果矩阵有逆则返回真，否则返回假
说明：只有方阵才有其逆矩阵
**********************************************************/
bool MathMetric::inverse(double* a,int n)
{
	int *is,*js,i,j,k,l,u,v;
    double d,p;
    is=(int*)malloc(n*sizeof(int));
    js=(int*)malloc(n*sizeof(int));
    for (k=0; k<=n-1; k++)
      { d=0.0;
        for (i=k; i<=n-1; i++)
        for (j=k; j<=n-1; j++)
          {
			l=i*n+j;
			p=fabs(a[l]);
            if (p>d)
			{
				d=p;
				is[k]=i;
				js[k]=j;
			}
          }
        if (d+1.0==1.0)
          {
			free(is);
			free(js);
			printf("该矩阵无逆阵。\n");
            return(false);
          }
        if (is[k]!=k)
          for (j=0; j<=n-1; j++)
            {
			  u=k*n+j;
			  v=is[k]*n+j;
              p=a[u];
			  a[u]=a[v];
			  a[v]=p;
            }
        if (js[k]!=k)
          for (i=0; i<=n-1; i++)
            {
			  u=i*n+k;
			  v=i*n+js[k];
              p=a[u];
			  a[u]=a[v];
			  a[v]=p;
            }
        l=k*n+k;
        a[l]=1.0/a[l];
        for (j=0; j<=n-1; j++)
          if (j!=k)
            {
			  u=k*n+j;
			  a[u]=a[u]*a[l];
		  }
        for (i=0; i<=n-1; i++)
          if (i!=k)
            for (j=0; j<=n-1; j++)
              if (j!=k)
                { u=i*n+j;
                  a[u]=a[u]-a[i*n+k]*a[k*n+j];
                }
        for (i=0; i<=n-1; i++)
          if (i!=k)
            { u=i*n+k; a[u]=-a[u]*a[l];}
      }
    for (k=n-1; k>=0; k--)
      { if (js[k]!=k)
          for (j=0; j<=n-1; j++)
            { u=k*n+j; v=js[k]*n+j;
              p=a[u]; a[u]=a[v]; a[v]=p;
            }
        if (is[k]!=k)
          for (i=0; i<=n-1; i++)
            { u=i*n+k; v=i*n+is[k];
              p=a[u]; a[u]=a[v]; a[v]=p;
            }
      }
    free(is);
	free(js);
	return true;
}

/**********************************************************
函数名：operator +
功能：对矩阵重载"+"运算符
入口参数：Metric1:加数矩阵
出口参数：*result:相加后所得结果
说明：结果也是一个矩阵,其维数为第被加矩阵的行，加矩阵的列
**********************************************************/
MathMetric & MathMetric::operator +(MathMetric &Metric1)
{
	MathMetric *result;
	if((Metric1.clum!=clum)||(Metric1.line!=line))
		return *(MathMetric*)NULL;
	result=new MathMetric(this->data,line,clum);
	for(unsigned int i=0;i<line*clum;i++)
		result->data[i]+=Metric1.data[i];
	return *result;
}


/**********************************************************
函数名：operator -
功能：对矩阵重载"-"运算符
入口参数：Metric1:减数矩阵
出口参数：*result:相减后所得结果
说明：结果也是一个矩阵,其维数为第被减矩阵的行，减矩阵的列
**********************************************************/
MathMetric & MathMetric::operator -(MathMetric &Metric1)
{
	MathMetric *result;
	if((Metric1.clum!=clum)||(Metric1.line!=line))
		return *(MathMetric*)NULL;
	result=new MathMetric(this->data,line,clum);
	for(unsigned int i=0;i<line*clum;i++)
		result->data[i]-=Metric1.data[i];
	return *result;
}


/**********************************************************
函数名：operator -
功能：对矩阵重载"-"运算符
入口参数：Metric1:减数矩阵
出口参数：*result:相减后所得结果
说明：结果也是一个矩阵,其维数为第被减矩阵的行，减矩阵的列
**********************************************************/
MathMetric & MathMetric::operator -(void)
{
	MathMetric *result;
	result=new MathMetric(this->data,line,clum);
	for(unsigned int i=0;i<line*clum;i++)
		result->data[i]=-result->data[i];
	return *result;
}



/**********************************************************
函数名：operator *
功能：对矩阵重载"*"运算符
入口参数：Metric1:除数矩阵
出口参数：*result:相乘后所得结果
说明：结果也是一个矩阵,其维数为第被乘矩阵的行，乘矩阵的列
**********************************************************/
MathMetric & MathMetric::operator *(MathMetric &Metric1)
{

	MathMetric *result;
	double *res;
	if(clum!=Metric1.line)
		return *(MathMetric*)NULL;
	res=multiple(this->data,line,clum,Metric1.data,Metric1.line,Metric1.clum);
	result=new MathMetric(res,line,Metric1.clum);
	free(res);
	return *result;
}


/**********************************************************
函数名：operator /
功能：对矩阵重载/运算符
入口参数：Metric1:除数矩阵
出口参数：*result:相除后所得结果
说明：结果也是一个矩阵,其维数为第被除矩阵的行，除矩阵的列
**********************************************************/
MathMetric & MathMetric::operator /(MathMetric &Metric1)
{
	double *res;
	MathMetric *result=NULL;
	MathMetric temp(Metric1.data,Metric1.line,Metric1.clum);
	if((clum!=Metric1.line)&&(Metric1.line==Metric1.clum))
		return *(MathMetric*)NULL;
	inverse(temp.data,temp.line);
	res=multiple(this->data,line,clum,temp.data,temp.line,temp.clum);
	result=new MathMetric(res,this->line,temp.clum);
	return *result;

}


/**********************************************************
函数名：print
功能：将矩阵与文本形式输出，矩阵一行输出一列，每个元素用tab分开
入口参数：无
出口参数：成功返回true,失败返回false
说明：
**********************************************************/
bool MathMetric::print()
{
	char *buf;
	buf=(char*)malloc(line*clum*20);
	if(!buf)
		return false;
	memset(buf,'\0',line*clum*20);
	for(unsigned int i=0;i<line;i++)
	{
		for(unsigned int n=0;n<clum;n++)
		{
			sprintf(buf+strlen(buf),"%.4f	",this->data[i*clum+n]);
		}
		sprintf(buf+strlen(buf),"\n");
	}
	printf(buf);
	free(buf);
	return true;
}

/**********************************************************
函数名：print
功能：将矩阵与文本形式输出，矩阵一行输出一列，每个元素用tab分开
入口参数：无
出口参数：成功返回true,失败返回false
说明：
**********************************************************/
unsigned MathMetric::get_line()
{
	return this->line;
}

/**********************************************************
函数名：print
功能：将矩阵与文本形式输出，矩阵一行输出一列，每个元素用tab分开
入口参数：无
出口参数：成功返回true,失败返回false
说明：
**********************************************************/
unsigned MathMetric::get_colum()
{
	return this->clum;
}

/**********************************************************
函数名：set_line
功能：设置矩阵的列属性值为line参数指的值
入口参数：line:矩阵新的列属性值
出口参数：无，其总是成功完成
说明：
**********************************************************/
void MathMetric::set_line(unsigned int line)
{
	this->line=line;
}

/**********************************************************
函数名：set_colum
功能：设置矩阵的列属性值为colum参数指的值
入口参数：colum:矩阵新的列属性值
出口参数：无，其总是成功完成
说明：
**********************************************************/
void MathMetric::set_colum(unsigned int colum)
{
	this->clum=colum;
}

/**********************************************************
函数名：get_data
功能：获取矩阵元素的数据指针
入口参数：无
出口参数：返回矩阵元素的数据指针，其总是能成功完成
说明：
**********************************************************/
double* MathMetric::get_data()
{
	return this->data;
}


/**********************************************************
函数名：set_data
功能：重新设置矩无素的数据指针
入口参数：data:矩阵新的元素数据指针
出口参数：无，其总能成功完成
说明：矩阵元素的数据指针是指存放矩阵元素值的数组的第一个字节地址
**********************************************************/
void MathMetric::set_data(double *data)
{
	this->data=data;
}



/**********************************************************
函数名：reverse
功能：求矩阵的转置矩阵
入口参数：无
出口参数：成功返回true，失败返回false
说明：些函数的功能与静态函数reverse的功能完全相同,只是其作为
	  矩阵类的成员函数，必须构造对象以后方能使用
**********************************************************/
bool MathMetric::reverse()
{

	return reverse(this->data,this->line,this->clum);

}

